#include "SyncQueue.h"
#include <functional>
#include <atomic>
#include <thread>

const int MaxTaskCount = 100;

class ThreadPool
{
public:
    using Task = std::function<void()>;

    ThreadPool(uint32_t numThreads = std::thread::hardware_concurrency(), int taskCount = MaxTaskCount)
        : m_queue(taskCount)
    { //使用CPU核数来创建线程，以达到最优的效率

        Start(numThreads);
    }

    ~ThreadPool(void)
    {
        Stop(); //在析构函数出，停止所有线程
    }

    void Stop()
    {
        std::call_once(m_flag, [this]()
                       { StopThreadGroup(); }); //函数值调用一次
    }

    void AddTask(Task &&task) //移动语义的方式传入函数内
    {
        m_queue.Put(std::forward<Task>(task)); //使用完美转发的方式，保持参数的右值属性
    }

    void AddTask(const Task &task)
    {
        m_queue.Put(task); //引用传入
    }

private:
    void Start(int numThreads)
    {
        m_running = true;
        for (size_t i = 0; i < numThreads; i++)
        {
            m_threadGroup.push_back(std::make_shared<std::thread>(&ThreadPool::RunInthread, this)); //以智能指针的存储方式创建线程并塞入容器中，来延长线程的生命周期
            //线程创建时，即开始运行线程函数
        }
    }

    void RunInthread()
    {
        while (m_running)
        {
            std::list<Task> list;
            m_queue.Take(list);
            for (auto &task : list) //从链表中取出任务并执行
            {
                if (!m_running)
                    return;
                task(); //处理对应的任务
            }
        }
    }

    void StopThreadGroup()
    {
        m_queue.Stop();                   //让同步队列的线程停止
        m_running = false;                //将内部线程跳出循环并等待
        for (auto thread : m_threadGroup) //等待线程结束
        {
            if (thread)
                thread->join();
        }

        m_threadGroup.clear();
    }
    std::list<std::shared_ptr<std::thread>> m_threadGroup; //处理任务的线程组
    SyncQueue<Task> m_queue;                               //同步队列
    std::atomic_bool m_running;                            //是否停止的标志，采用原子变量 比互斥锁更高效
    std::once_flag m_flag;                                 //只调用一次
};